package org.me.runaway;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.CheckBox;
import android.widget.Toast;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;

/**
 * @author RunAway
 */
public class MainActivity extends MapActivity {

    public static final String NAMESPACE = "http://queryDB/";
    private static final String METHOD_NAME = "downloadBD";
    private static final String ACTION = "downloadDB";
    //em vez de ter localhost, precisa de ter o IP do pc, por causa do localhost entra em conflito com o netbeans
    //so funciona com o IP da interface activa
//    public static final String URL = "http://172.16.4.36:8080/RunAwayDatabaseServer/QueryDatabaseService";
    public static final String URL="http://192.168.1.2:43704/RunAwayDatabaseServer/QueryDatabaseService";

    public static final String SEARCH_OPTION = "Pesquisa";
    public static final String FAVORITES_OPTION = "Favoritos";
    public static final String ABOUT_OPTION = "Sobre...";
    public static final String EXIT_OPTION = "Sair";

    Intent List;
    Intent map;
    SoapObject request;
    List<Place> places = new ArrayList<Place>();
    DB_Adapter db = null;
    Cursor cursor;
    private MapController mapController;
    MapView mapView;
    private LocationManager lm;
    private ProgressDialog progressDialog;
    private AutoCompleteList names = new AutoCompleteList();
    int option = -1;
    AutoCompleteTextView autoTv1;
    CheckBox restaurante;
    CheckBox hotel;
    CheckBox museu;
    MapItemizedOverlay itemizedOverlay;
    List<Overlay> mapOverlays;
    Drawable drawable;
    Bundle extras;

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main);
        StatusGPS.setStatus(" ");

        db = new DB_Adapter(this);
        StatusGPS.setMyPosition(new GeoPoint((int) (40.631005 * 1E6), (int) (-8.655907 * 1E6)));

        String id;

        loadMap();

        extras = getIntent().getExtras();

        lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, new LocatListener());

        if (extras == null) {
            ProgressDownloadExtBD();
            mapController.setCenter(StatusGPS.getMyPosition());
            loadOverlays(true);
        }
        if (extras != null) {
            id = extras.getString("id");

            if (!id.equals("myLocation")) {
                StatusGPS.setToPosition(new GeoPoint(getLat(id), getLon(id)));
                mapController.setCenter(StatusGPS.getToPosition());
            } else {
                mapController.setCenter(StatusGPS.getMyPosition());
            }

            loadOverlays(id.equals("myLocation"));
        }

        MapOverlay mapOverlay = new MapOverlay();
        List<Overlay> listOfOverlays = mapView.getOverlays();
        listOfOverlays.add(mapOverlay);
    }

    @Override
    protected boolean isRouteDisplayed() {
        return false;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add(0, 0, 0, SEARCH_OPTION).setIcon(R.drawable.search);
        menu.add(0, 1, 0, FAVORITES_OPTION).setIcon(R.drawable.favorites);
        menu.add(0, 2, 0, ABOUT_OPTION).setIcon(R.drawable.info);
        menu.add(0, 3, 0, EXIT_OPTION).setIcon(R.drawable.logout);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case 0:
                search();
                return true;
            case 1:
                List = new Intent(this, PlaceList.class);
                List.putExtra("favorites", true);
                startActivity(List);
                this.finish();
                return true;
            case 2:
                showAbout();
                return true;
            case 3:
                this.finish();
                break;
        }
        return false;

    }

    private void loadMap() {
        mapView = (MapView) findViewById(R.id.mapview);
        mapView.displayZoomControls(true);
        mapView.setClickable(true);


        MapView.LayoutParams lp;
        lp = new MapView.LayoutParams(MapView.LayoutParams.WRAP_CONTENT, MapView.LayoutParams.WRAP_CONTENT, 10, 10, MapView.LayoutParams.TOP_LEFT);
        View zoomControls = mapView.getZoomControls();
        mapView.addView(zoomControls, lp);

        mapController = mapView.getController();
        mapController.setZoom(12);
    }

    private boolean downloadExtDB() {

        places = new ArrayList<Place>();
        String s = new String();
        Place p = new Place();

        request = new SoapObject(NAMESPACE, METHOD_NAME);

        SoapSerializationEnvelope soapEnvelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        soapEnvelope.setOutputSoapObject(request);
        HttpTransportSE aht = new HttpTransportSE(URL);

        aht.setXmlVersionTag("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        try {
            aht.call(ACTION, soapEnvelope);
        } catch (IOException ex) {
            return false;
        } catch (XmlPullParserException ex) {
            return false;
        }

        SoapObject result = (SoapObject) soapEnvelope.bodyIn;

        if (result.getPropertyCount() > 0) {
            for (int i = 0; i < result.getPropertyCount(); i++) {
                s = result.getProperty(i).toString();
                p = Place.parsePlace(s);
                places.add(p);
            }
        }
        return true;
    }

    public boolean updateAppDB() {
        long id = -1;
        Place p = new Place();
        db.open();

        for (int i = 0; i < places.size(); i++) {
            if (!placeExists(places.get(i).getName())) {
                db.insertPlace(places.get(i));
            }
            else{
                if (places.get(i).isUpdated()) {
                    id = db.getId(places.get(i).getName());
                    if (id != -1) {
                        p = db.getPlace(id);
                        places.get(i).setFavorite(p.isFavorite());
                        places.get(i).setVoted(p.isVoted());
                        db.updatePlace(id, places.get(i));
                    }
                }
            }
        }
        deleteOldEntries();
        db.close();
        return true;

    }

    private boolean placeExists(String name){
        boolean status;
        if (db.queryByName(name)){
            status = true;
        }
        else{
            status = false;
        }
        return status;
    }

    private boolean deleteOldEntries() {
        if (places.size() > 0) {
            Cursor c = db.getAllPlaces();
            String s = "";
            Boolean status = false;
            long id = -1;

            try {
                if (c != null) {
                    c.moveToFirst();
                    for (int i = 0; i < c.getCount(); i++) {
                        status = false;
                        s = c.getString(c.getColumnIndex(Place.KEY_NAME));
                        for (int j = 0; j < places.size(); j++) {
                            if (s.equals(places.get(j).getName())) {
                                status = true;
                            }
                        }
                        if (status == false) {
                            id = db.getId(s);
                            if (id != -1) {
                                db.deletePlace(id);
                            }
                        }
                        c.moveToNext();
                    }
                }

                return true;
            } catch (Exception e) {
                return false;
            }
        }
        return false;
    }

    private void search() {

        LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
        View layout = inflater.inflate(R.layout.searchdialog, (ViewGroup) findViewById(R.id.root));

        String[] nameList = names.getAll(getBaseContext());
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_dropdown_item_1line, nameList);

        autoTv1 = (AutoCompleteTextView) layout.findViewById(R.id.autocomplete);
        restaurante = (CheckBox) layout.findViewById(R.id.check1);
        hotel = (CheckBox) layout.findViewById(R.id.check2);
        museu = (CheckBox) layout.findViewById(R.id.check3);
        autoTv1.setThreshold(1);
        autoTv1.setDropDownHeight(100);
        autoTv1.setAdapter(adapter);

        AlertDialog.Builder builder = new AlertDialog.Builder(this);

        builder.setMessage("Pesquisar: ");
        builder.setView(layout);
        builder.setPositiveButton("Pesquisar",
                new DialogInterface.OnClickListener() {

                    public void onClick(DialogInterface dialog, int id) {
                        chooseSearchOption();
                        startActivity(List);
                        MainActivity.this.finish();
                    }
                });
        builder.setNegativeButton("Cancelar",
                new DialogInterface.OnClickListener() {

                    public void onClick(DialogInterface dialog, int id) {
                        dialog.dismiss();
                    }
                });
        AlertDialog alert = builder.create();
        alert.show();
    }

    private void chooseSearchOption() {
        if (restaurante.isChecked() && !hotel.isChecked() && !museu.isChecked()) {
            option = 0;
        } else if (hotel.isChecked() && !restaurante.isChecked() && !museu.isChecked()) {
            option = 1;
        } else if (museu.isChecked() && !restaurante.isChecked() && !hotel.isChecked()) {
            option = 2;
        } else if (hotel.isChecked() && restaurante.isChecked() && !museu.isChecked()) {
            option = 3;
        } else if (hotel.isChecked() && museu.isChecked() && !restaurante.isChecked()) {
            option = 4;
        } else if (restaurante.isChecked() && museu.isChecked() && !hotel.isChecked()) {
            option = 5;
        } else {
            option = 6;
        }

        switch (option) {
            case 0:
                List = new Intent(MainActivity.this, PlaceList.class);
                List.putExtra("option", 0);
                List.putExtra("name", autoTv1.getText().toString());
                break;
            case 1:
                List = new Intent(MainActivity.this, PlaceList.class);
                List.putExtra("option", 1);
                List.putExtra("name", autoTv1.getText().toString());
                break;
            case 2:
                List = new Intent(MainActivity.this, PlaceList.class);
                List.putExtra("option", 2);
                List.putExtra("name", autoTv1.getText().toString());
                break;
            case 3:
                List = new Intent(MainActivity.this, PlaceList.class);
                List.putExtra("option", 3);
                List.putExtra("name", autoTv1.getText().toString());
                break;
            case 4:
                List = new Intent(MainActivity.this, PlaceList.class);
                List.putExtra("option", 4);
                List.putExtra("name", autoTv1.getText().toString());
                break;
            case 5:
                List = new Intent(MainActivity.this, PlaceList.class);
                List.putExtra("option", 5);
                List.putExtra("name", autoTv1.getText().toString());
                break;
            case 6:
                if (autoTv1.getText().length() > 0) {
                    List = new Intent(MainActivity.this, PlaceList.class);
                    List.putExtra("option", 6);
                    List.putExtra("name", autoTv1.getText().toString());
                } else {
                    List = new Intent(MainActivity.this, PlaceList.class);
                    List.putExtra("option", 6);
                    List.putExtra("all", true);
                }
                break;
        }
    }

    private boolean isNear(double latPark, double lonPark, GeoPoint mypointActuate) {
        double raio = 1500;
        double latActual = mypointActuate.getLatitudeE6();
        double lonActual = mypointActuate.getLongitudeE6();

        double tmp = ((latPark - latActual) / 111) * ((latPark - latActual) / 111) + ((lonPark - lonActual) / 60) * ((lonPark - lonActual) / 60);
        double distance = Math.sqrt(tmp);


        if (distance < raio) {
            return true;
        } else {
            return false;
        }
    }

    private void loadOverlays(boolean raio) {
        db.open();
        cursor = db.queryPositions();

        if (cursor != null) {
            cursor.moveToFirst();

            for (int i = 0; i < cursor.getCount(); i++) {

                String nome = cursor.getString(cursor.getColumnIndex(Place.KEY_NAME));
                double lat = cursor.getDouble(cursor.getColumnIndex(Place.KEY_LAT));
                double lng = cursor.getDouble(cursor.getColumnIndex(Place.KEY_LNG));
                String type = cursor.getString(cursor.getColumnIndex(Place.KEY_TYPE));

                int l1 = (int) (lat * 1E6);
                int l2 = (int) (lng * 1E6);
                GeoPoint point = new GeoPoint(l1, l2);

                mapOverlays = mapView.getOverlays();

                if (type.equals("Museu")) {
                    drawable = this.getResources().getDrawable(R.drawable.museum);
                } else if (type.equals("Restaurante")) {
                    drawable = this.getResources().getDrawable(R.drawable.restaurante);
                } else if (type.equals("Hotel")) {
                    drawable = this.getResources().getDrawable(R.drawable.hotel);
                } else {
                    Toast.makeText(this, type.toString(), Toast.LENGTH_LONG);
                }


                itemizedOverlay = new MapItemizedOverlay(drawable, this);

                if (raio) {

                    if (isNear(point.getLatitudeE6(), point.getLongitudeE6(), StatusGPS.getMyPosition())) {
                        OverlayItem overlayitem = new OverlayItem(point, nome, lat + ", " + lng);
                        itemizedOverlay.addOverlay(overlayitem);
                        mapOverlays.add(itemizedOverlay);
                    }
                } else {
                    OverlayItem overlayitem = new OverlayItem(point, nome, lat + ", " + lng);
                    itemizedOverlay.addOverlay(overlayitem);
                    mapOverlays.add(itemizedOverlay);
                }
                cursor.moveToNext();
            }
        }
        db.close();


        drawable = this.getResources().getDrawable(R.drawable.mylocation);
        itemizedOverlay = new MapItemizedOverlay(drawable, this);
        OverlayItem overlayitem = new OverlayItem(StatusGPS.getMyPosition(), "Localização Actual", StatusGPS.getMyPosition().getLatitudeE6() / 1E6 + ", " + StatusGPS.getMyPosition().getLongitudeE6() / 1E6);
        itemizedOverlay.addOverlay(overlayitem);
        mapOverlays.add(itemizedOverlay);


    }

    public int getLat(String id) {
        db.open();
        cursor = db.queryPositions();
        startManagingCursor(cursor);
        cursor.moveToFirst();
        int result = 0;
        for (int i = 0; i < cursor.getCount(); i++) {
            String item = cursor.getString(cursor.getColumnIndex(Place.KEY_ROWID));
            if (item.equals(id)) {
                double lat = cursor.getDouble(cursor.getColumnIndex(Place.KEY_LAT));
                result = (int) (lat * 1E6);
            }
            cursor.moveToNext();
        }
        db.close();
        return result;
    }

    private int getLon(String id) {
        db.open();
        cursor = db.queryPositions();
        startManagingCursor(cursor);
        cursor.moveToFirst();

        int result = 0;
        for (int i = 0; i < cursor.getCount(); i++) {
            String item = cursor.getString(cursor.getColumnIndex(Place.KEY_ROWID));
            if (item.equals(id)) {
                double lon = cursor.getDouble(cursor.getColumnIndex(Place.KEY_LNG));
                result = (int) (lon * 1E6);
            }
            cursor.moveToNext();
        }
        db.close();
        return result;
    }

    //centrar mapa posição actual
    private class LocatListener implements LocationListener {

        public void onLocationChanged(Location argLocation) {
            StatusGPS.setMyPosition(new GeoPoint(
                    (int) (argLocation.getLatitude() * 1000000),
                    (int) (argLocation.getLongitude() * 1000000)));

            if (!StatusGPS.getStatus().equals("route")) {

                if (mapOverlays != null) {
                    mapOverlays.clear();
                }
                mapController.setCenter(StatusGPS.getMyPosition());
                loadOverlays(true);
            } else {
                map = new Intent(getBaseContext(), GPS.class);
                startActivity(map);
            }


        }

        public void onProviderDisabled(String provider) {
            // TODO Auto-generated method stub
        }

        public void onProviderEnabled(String provider) {
            // TODO Auto-generated method stub
        }

        public void onStatusChanged(String provider,
                int status, Bundle extras) {
            // TODO Auto-generated method stub
        }
    }

    public void ProgressDownloadExtBD() {
        progressDialog = ProgressDialog.show(MainActivity.this, "Espere, por favor...", "Actualizar dados da Base de Dados da aplicação", true);
        new Thread() {

            public void run() {
                try {
                    downloadExtDB();
                    sleep(1000);
                    updateAppDB();
                    sleep(1000);
                } catch (Exception e) {
                }
                progressDialog.dismiss();
            }
        }.start();

    }

    private void showAbout() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setIcon(R.drawable.info);
        builder.setTitle("Sobre...");
        builder.setMessage("Esta aplicação foi desenvolvida por:\nPaulo Oliveira\nAndré Oliveira\n\nNo âmbito da disciplina de ICM, pertencente ao curso TSI da Universidade de Aveiro.");
        builder.setPositiveButton("Ok",
                new DialogInterface.OnClickListener() {

                    public void onClick(DialogInterface dialog, int id) {
                        dialog.dismiss();
                    }
                });
        AlertDialog alert = builder.create();
        alert.show();
    }

    final public Context getContext() {
        return this.getBaseContext();
    }

    class MapOverlay extends com.google.android.maps.Overlay {

        @Override
        public boolean onTouchEvent(MotionEvent event, MapView mapView) {
            return false;
        }
    }
}

